package com.brillilab.message.core;

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.push.model.v20160801.PushRequest;
import com.aliyuncs.push.model.v20160801.PushResponse;
import com.aliyuncs.utils.ParameterHelper;
import com.brillilab.domain.po.message.Message;
import com.brillilab.message.vo.AppExtData;
import com.brillilab.message.vo.AppMessageVo;
import com.brillilab.service.core.message.IMessageService;
import com.brillilab.service.module.message.template.enums.MessageTypeEnum;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;

@Component
@ConfigurationProperties(prefix="aliyun.push")
@Data
@Slf4j
public class AppMessageSender implements MessageSender<AppMessageVo> {

    private String regionId;
    private String accessKeyId;
    private String accessKeySecret;
    private long androidKey;
    private long iosKey;
    private String env;

    @Resource
    private IMessageService messageService;

    private DefaultAcsClient getClient() {
        IClientProfile profile=DefaultProfile.getProfile(regionId,accessKeyId,accessKeySecret);
        return new DefaultAcsClient(profile);
    }

    @Override
    public boolean sendMessage(AppMessageVo messageVo) {

        AppExtData appExtData=new AppExtData(messageVo.getId(),messageVo.getType(),messageVo.getReferId(),messageVo.getExtParameters());

        PushRequest pushRequest=new PushRequest();
        pushRequest.setProtocol(ProtocolType.HTTPS);// 安全性比较高的内容建议使用HTTPS
        pushRequest.setMethod(MethodType.POST);// 内容较大的请求，使用POST请求
        pushRequest.setTarget("ACCOUNT"); //推送目标: DEVICE:按设备推送 ALIAS : 按别名推送 ACCOUNT:按帐号推送  TAG:按标签推送; ALL: 广播推送
        pushRequest.setTargetValue(messageVo.getAccount());
        pushRequest.setPushType(messageVo.getPushType()); // 消息类型 MESSAGE NOTICE
        pushRequest.setDeviceType("ALL"); // 设备类型 ANDROID iOS ALL.
        pushRequest.setTitle(messageVo.getTitle()); // 消息的标题
        if(messageVo.getExtParameters()!=null){
            JSONObject exData=JSONObject.parseObject(messageVo.getExtParameters());
            pushRequest.setBody(exData.getString("content")); // 消息的内容
        }

        //IOS
        pushRequest.setIOSApnsEnv(env);
        pushRequest.setIOSMusic("default");
        pushRequest.setIOSMutableContent(true);//是否允许扩展iOS通知内容
        pushRequest.setIOSExtParameters(JSONObject.toJSONString(appExtData)); //通知的扩展属性(注意 :该参数要以json map的格式传入,否则会解析出错)
        if(env.equals("PRODUCT")){
            pushRequest.setIOSRemind(false);//消息推送时设备不在线（既与移动推送的服务端的长连接通道不通），则这条推送会做为通知，通过苹果的APNs通道送达一次。注意：离线消息转通知仅适用于生产环境
            pushRequest.setIOSRemindBody(messageVo.getBody());
        }

        //Android
        pushRequest.setAndroidMusic("default");
        pushRequest.setAndroidPopupTitle(messageVo.getTitle());
        pushRequest.setAndroidPopupBody(messageVo.getBody());
        pushRequest.setAndroidExtParameters(JSONObject.toJSONString(appExtData));

        // 推送控制
        Date pushDate=new Date(System.currentTimeMillis()); // 30秒之间的时间点,也可以设置成你指定固定时间
        String pushTime=ParameterHelper.getISO8601Time(pushDate);
        pushRequest.setPushTime(pushTime); // 延后推送。可选，如果不设置表示立即推送
        String expireTime=ParameterHelper.getISO8601Time(new Date(System.currentTimeMillis() + 12 * 3600 * 1000)); // 12小时后消息失效,不会再发送
        pushRequest.setExpireTime(expireTime);
        // 离线消息是否保存,若保存, 在推送时候，用户即使不在线，下一次上线则会收到
        if(messageVo.getType().equals(MessageTypeEnum.PushMessage.getValue())) {
            pushRequest.setStoreOffline(false); //消息：离线消息不保存
        }else{
            pushRequest.setStoreOffline(true); //通知：保存离线消息
        }

        try {
            pushRequest.setAppKey(iosKey);
            PushResponse iosRes=this.getClient().getAcsResponse(pushRequest);
            log.info("ios推送结果 messageId：{},推送类型：{}",iosRes.getMessageId(),messageVo.getPushType());

            pushRequest.setAppKey(androidKey);
            // 指定notificaitonchannel id
            pushRequest.setAndroidNotificationChannel("1");
            PushResponse androidRes=this.getClient().getAcsResponse(pushRequest);
            log.info("android推送结果 messageId：{},推送类型：{}",androidRes.getMessageId(),messageVo.getPushType());
            return true;
        } catch (ClientException e) {
            log.error("消息推送失败！",e);
            return false;
        }
    }

    /**
     *  推送人数在100以上
     * @param appMessageVo
     * @return
     */
    public boolean sendMessageMoreThan100(AppMessageVo appMessageVo) {
        String accountsStr = appMessageVo.getAccount();
        String[] accounts = accountsStr.split(",");
        int num = accounts.length;
        while (num>0){
            int start = num-100 >= 0 ? num-100 : 0;
            appMessageVo.setAccount(StringUtils.join(Arrays.copyOfRange(accounts,start,num),','));
            this.sendMessage(appMessageVo);
            num-=100;
        }
        return true;
    }

    @Override
    public AppMessageVo buildMessageVo(String messageData) {

        Message message=JSONObject.parseObject(messageData,Message.class);

        Assert.notNull(message,String.format("消息不存在！msgData : %s",messageData));

        String account = StringUtils.isNotBlank(message.getReceiverIds()) ? message.getReceiverIds(): message.getReceiverId().toString();

        return new AppMessageVo(message.getId(),account,message.getTitle(),message.getContent(),message.getData(),message.getType(),message.getReferId(),message.getPushType());
    }
}
